--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
meshchatx/src/frontend/js/mapGeodesy.js e0f1f99cd1c208c5008a936230c38e448dddd45d (e0f1f99c) Text, 5.63 KB
T8b949e// SPDX-License-Identifier: 0BSD
Tff7b72import Tb4b4b4{ Te6edf3DEFAULT_RADIUSTb4b4b4, Te6edf3getDistance Tb4b4b4} Tff7b72from Ta5d6ff"ol/sphere"Tb4b4b4;
T8b949e/**
* @param {number} lon1
* @param {number} lat1
* @param {number} lon2
* @param {number} lat2
* @returns {number} Initial (forward) azimuth in degrees [0, 360), spherical model.
*/
Tff7b72export Tff7b72function Te6edf3sphericalInitialBearingDegTb4b4b4(Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4, Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3φ1 Tff7b72= Tb4b4b4(Te6edf3lat1 Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72/ T79c0ff180Tb4b4b4;
Tff7b72const Te6edf3φ2 Tff7b72= Tb4b4b4(Te6edf3lat2 Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72/ T79c0ff180Tb4b4b4;
Tff7b72const Te6edf3Δλ Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3lon2 Tff7b72- Te6edf3lon1Tb4b4b4) Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72/ T79c0ff180Tb4b4b4;
Tff7b72const Te6edf3y Tff7b72= Tffa657MathTb4b4b4.Te6edf3sinTb4b4b4(Te6edf3ΔλTb4b4b4) Tff7b72* Tffa657MathTb4b4b4.Te6edf3cosTb4b4b4(Te6edf3φ2Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3x Tff7b72= Tffa657MathTb4b4b4.Te6edf3cosTb4b4b4(Te6edf3φ1Tb4b4b4) Tff7b72* Tffa657MathTb4b4b4.Te6edf3sinTb4b4b4(Te6edf3φ2Tb4b4b4) Tff7b72- Tffa657MathTb4b4b4.Te6edf3sinTb4b4b4(Te6edf3φ1Tb4b4b4) Tff7b72* Tffa657MathTb4b4b4.Te6edf3cosTb4b4b4(Te6edf3φ2Tb4b4b4) Tff7b72* Tffa657MathTb4b4b4.Te6edf3cosTb4b4b4(Te6edf3ΔλTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3θ Tff7b72= Tffa657MathTb4b4b4.Te6edf3atan2Tb4b4b4(Te6edf3yTb4b4b4, Te6edf3xTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4(Tb4b4b4(Tb4b4b4(Tb4b4b4(Te6edf3θ Tff7b72* T79c0ff180Tb4b4b4) Tff7b72/ Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72% T79c0ff360Tb4b4b4) Tff7b72+ T79c0ff360Tb4b4b4) Tff7b72% T79c0ff360Tb4b4b4;
Tb4b4b4}
T8b949e/**
* Rhumb-line distance and constant bearing on the sphere (mean Earth radius).
* @param {number} lon1
* @param {number} lat1
* @param {number} lon2
* @param {number} lat2
* @param {number} [radius]
* @returns {{ distanceMeters: number, bearingDeg: number }}
*/
Tff7b72export Tff7b72function Te6edf3rhumbLineMetricsTb4b4b4(Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4, Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4, Te6edf3radius Tff7b72= Te6edf3DEFAULT_RADIUSTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3R Tff7b72= Te6edf3radiusTb4b4b4;
Tff7b72const Te6edf3φ1 Tff7b72= Tb4b4b4(Te6edf3lat1 Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72/ T79c0ff180Tb4b4b4;
Tff7b72const Te6edf3φ2 Tff7b72= Tb4b4b4(Te6edf3lat2 Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72/ T79c0ff180Tb4b4b4;
Tff7b72let Te6edf3Δλ Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3lon2 Tff7b72- Te6edf3lon1Tb4b4b4) Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72/ T79c0ff180Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3Δλ Tff7b72> Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tb4b4b4{
Te6edf3Δλ Tff7b72-= T79c0ff2 Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3Δλ Tff7b72< Tff7b72-Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tb4b4b4{
Te6edf3Δλ Tff7b72+= T79c0ff2 Tff7b72* Tffa657MathTb4b4b4.Te6edf3PITb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3Δφ Tff7b72= Te6edf3φ2 Tff7b72- Te6edf3φ1Tb4b4b4;
Tff7b72const Te6edf3Δψ Tff7b72= Tffa657MathTb4b4b4.Te6edf3logTb4b4b4(Tffa657MathTb4b4b4.Te6edf3tanTb4b4b4(Tffa657MathTb4b4b4.Te6edf3PI Tff7b72/ T79c0ff4 Tff7b72+ Te6edf3φ2 Tff7b72/ T79c0ff2Tb4b4b4) Tff7b72/ Tffa657MathTb4b4b4.Te6edf3tanTb4b4b4(Tffa657MathTb4b4b4.Te6edf3PI Tff7b72/ T79c0ff4 Tff7b72+ Te6edf3φ1 Tff7b72/ T79c0ff2Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3q Tff7b72= Tffa657MathTb4b4b4.Te6edf3absTb4b4b4(Te6edf3ΔψTb4b4b4) Tff7b72> T79c0ff1e-12 Tff7b72? Te6edf3Δφ Tff7b72/ Te6edf3Δψ Tff7b72: Tffa657MathTb4b4b4.Te6edf3cosTb4b4b4(Te6edf3φ1Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3dist Tff7b72= Tffa657MathTb4b4b4.Te6edf3sqrtTb4b4b4(Te6edf3Δφ Tff7b72* Te6edf3Δφ Tff7b72+ Te6edf3q Tff7b72* Te6edf3q Tff7b72* Te6edf3Δλ Tff7b72* Te6edf3ΔλTb4b4b4) Tff7b72* Te6edf3RTb4b4b4;
Tff7b72const Te6edf3bearingDeg Tff7b72= Tb4b4b4(Tb4b4b4(Tb4b4b4(Tb4b4b4(Tffa657MathTb4b4b4.Te6edf3atan2Tb4b4b4(Te6edf3ΔλTb4b4b4, Te6edf3ΔψTb4b4b4) Tff7b72* T79c0ff180Tb4b4b4) Tff7b72/ Tffa657MathTb4b4b4.Te6edf3PITb4b4b4) Tff7b72% T79c0ff360Tb4b4b4) Tff7b72+ T79c0ff360Tb4b4b4) Tff7b72% T79c0ff360Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3distanceMetersTff7b72: Te6edf3distTb4b4b4, Te6edf3bearingDeg Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e/**
* Great-circle (geodesic on sphere) distance matches OpenLayers {@link import("ol/sphere").getLength}
* for a two-point line in WGS84.
*
* @param {number} lon1
* @param {number} lat1
* @param {number} lon2
* @param {number} lat2
* @returns {{
* geodesicMeters: number,
* forwardAzimuthDeg: number,
* backAzimuthDeg: number,
* rhumbMeters: number,
* rhumbBearingDeg: number,
* rhumbBackBearingDeg: number,
* }}
*/
Tff7b72export Tff7b72function Te6edf3computeSegmentMetricsTb4b4b4(Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4, Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3a Tff7b72= Tb4b4b4[Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3b Tff7b72= Tb4b4b4[Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3geodesicMeters Tff7b72= Te6edf3getDistanceTb4b4b4(Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3forwardAzimuthDeg Tff7b72= Te6edf3sphericalInitialBearingDegTb4b4b4(Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4, Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3backAzimuthDeg Tff7b72= Te6edf3sphericalInitialBearingDegTb4b4b4(Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4, Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rh Tff7b72= Te6edf3rhumbLineMetricsTb4b4b4(Te6edf3lon1Tb4b4b4, Te6edf3lat1Tb4b4b4, Te6edf3lon2Tb4b4b4, Te6edf3lat2Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rhumbBackBearingDeg Tff7b72= Tb4b4b4(Te6edf3rhTb4b4b4.Te6edf3bearingDeg Tff7b72+ T79c0ff180Tb4b4b4) Tff7b72% T79c0ff360Tb4b4b4;
Tff7b72return Tb4b4b4{
Te6edf3geodesicMetersTb4b4b4,
Te6edf3forwardAzimuthDegTb4b4b4,
Te6edf3backAzimuthDegTb4b4b4,
Te6edf3rhumbMetersTff7b72: Te6edf3rhTb4b4b4.Te6edf3distanceMetersTb4b4b4,
Te6edf3rhumbBearingDegTff7b72: Te6edf3rhTb4b4b4.Te6edf3bearingDegTb4b4b4,
Te6edf3rhumbBackBearingDegTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e/**
* @param {number} meters
* @returns {{ metric: string, imperial: string }}
*/
Tff7b72export Tff7b72function Te6edf3formatLengthPairMetersTb4b4b4(Te6edf3metersTb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3metricTb4b4b4;
Tff7b72let Te6edf3imperialTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3meters Tff7b72> T79c0ff100Tb4b4b4) Tb4b4b4{
Te6edf3metric Tff7b72= Ta5d6ff`Tffd700${Tffa657MathTb4b4b4.Te6edf3roundTb4b4b4(Tb4b4b4(Te6edf3meters Tff7b72/ T79c0ff1000Tb4b4b4) Tff7b72* T79c0ff100Tb4b4b4) Tff7b72/ T79c0ff100Tffd700}Ta5d6ff kmTa5d6ff`Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3metric Tff7b72= Ta5d6ff`Tffd700${Tffa657MathTb4b4b4.Te6edf3roundTb4b4b4(Te6edf3meters Tff7b72* T79c0ff100Tb4b4b4) Tff7b72/ T79c0ff100Tffd700}Ta5d6ff mTa5d6ff`Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3feet Tff7b72= Te6edf3meters Tff7b72* T79c0ff3.28084Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3feet Tff7b72> T79c0ff5280Tb4b4b4) Tb4b4b4{
Te6edf3imperial Tff7b72= Ta5d6ff`Tffd700${Tffa657MathTb4b4b4.Te6edf3roundTb4b4b4(Te6edf3meters Tff7b72* T79c0ff0.000621371 Tff7b72* T79c0ff100Tb4b4b4) Tff7b72/ T79c0ff100Tffd700}Ta5d6ff miTa5d6ff`Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3imperial Tff7b72= Ta5d6ff`Tffd700${Tffa657MathTb4b4b4.Te6edf3roundTb4b4b4(Te6edf3feet Tff7b72* T79c0ff100Tb4b4b4) Tff7b72/ T79c0ff100Tffd700}Ta5d6ff ftTa5d6ff`Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{ Te6edf3metricTb4b4b4, Te6edf3imperial Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e/**
* @param {ReturnType<typeof computeSegmentMetrics>} metrics
* @param {(key: string) => string} t i18n
* @returns {string}
*/
Tff7b72export Tff7b72function Te6edf3buildBearingOverlayHtmlTb4b4b4(Te6edf3metricsTb4b4b4, Te6edf3tTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3geo Tff7b72= Te6edf3formatLengthPairMetersTb4b4b4(Te6edf3metricsTb4b4b4.Te6edf3geodesicMetersTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rh Tff7b72= Te6edf3formatLengthPairMetersTb4b4b4(Te6edf3metricsTb4b4b4.Te6edf3rhumbMetersTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fd Tff7b72= Te6edf3metricsTb4b4b4.Te6edf3forwardAzimuthDegTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3bd Tff7b72= Te6edf3metricsTb4b4b4.Te6edf3backAzimuthDegTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rfd Tff7b72= Te6edf3metricsTb4b4b4.Te6edf3rhumbBearingDegTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rbd Tff7b72= Te6edf3metricsTb4b4b4.Te6edf3rhumbBackBearingDegTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4(
Ta5d6ff`Ta5d6ff<div class="text-left space-y-0.5">Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div class="font-semibold text-gray-900 dark:text-zinc-100">Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_geodesic"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff</div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div>Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3geoTb4b4b4.Te6edf3metricTb4b4b4)Tffd700}Ta5d6ff <span class="text-[10px] opacity-80">(Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3geoTb4b4b4.Te6edf3imperialTb4b4b4)Tffd700}Ta5d6ff)</span></div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div>Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_forward"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff: Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3fdTb4b4b4)Tffd700}Ta5d6ff°</div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div>Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_back"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff: Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3bdTb4b4b4)Tffd700}Ta5d6ff°</div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div class="mt-1 font-semibold text-gray-900 dark:text-zinc-100">Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_rhumb"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff</div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div>Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3rhTb4b4b4.Te6edf3metricTb4b4b4)Tffd700}Ta5d6ff <span class="text-[10px] opacity-80">(Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3rhTb4b4b4.Te6edf3imperialTb4b4b4)Tffd700}Ta5d6ff)</span></div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<div>Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_rhumb_line"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff: Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3rfdTb4b4b4)Tffd700}Ta5d6ff° / Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3rbdTb4b4b4)Tffd700}Ta5d6ff°</div>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff</div>Ta5d6ff`
Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e/**
* @param {ReturnType<typeof computeSegmentMetrics>} metrics
* @param {(key: string) => string} t
* @returns {string}
*/
Tff7b72export Tff7b72function Te6edf3buildBearingLiveTooltipHtmlTb4b4b4(Te6edf3metricsTb4b4b4, Te6edf3tTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3geo Tff7b72= Te6edf3formatLengthPairMetersTb4b4b4(Te6edf3metricsTb4b4b4.Te6edf3geodesicMetersTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fd Tff7b72= Te6edf3metricsTb4b4b4.Te6edf3forwardAzimuthDegTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rd Tff7b72= Te6edf3metricsTb4b4b4.Te6edf3rhumbBearingDegTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4(
Ta5d6ff`Ta5d6ff<span class="font-semibold">Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_geodesic"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff</span> Ta5d6ff` Tff7b72+
Ta5d6ff`Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3geoTb4b4b4.Te6edf3metricTb4b4b4)Tffd700}Ta5d6ff<br/>Ta5d6ff` Tff7b72+
Ta5d6ff`Ta5d6ff<span class="text-[10px] opacity-90">Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_forward"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff: Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3fdTb4b4b4)Tffd700}Ta5d6ff° · Ta5d6ff` Tff7b72+
Ta5d6ff`Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3tTb4b4b4(Ta5d6ff"map.bearing_rhumb_line"Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff: Tffd700${Te6edf3escapeHtmlTb4b4b4(Te6edf3rdTb4b4b4)Tffd700}Ta5d6ff°</span>Ta5d6ff`
Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3escapeHtmlTb4b4b4(Te6edf3sTb4b4b4) Tb4b4b4{
Tff7b72return Tffa657StringTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/&/gTb4b4b4, Ta5d6ff"&"Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/</gTb4b4b4, Ta5d6ff"<"Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/>/gTb4b4b4, Ta5d6ff">"Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/"/gTb4b4b4, Ta5d6ff"""Tb4b4b4)Tb4b4b4;
Tb4b4b4}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────